
package it.ibgka;



import it.enrollement.System_Param;
import it.ibs.IB_ZSS;
import it.user.User;
import it.utils.Hash;
import java.util.Random;
import jpair.pairing.BigInt;
import jpair.pairing.Point;


/**
 * Protocol IB-DB was obtained with minor changes from an elliptic version of the 
protocol for static groups given in Dutta and Barua [DUTTA2008PROVABLY]. In theis version of protocol is used IB_ZSS signature scheme.
 * 
 * [DUTTA2008PROVABLY] Dutta, Ratna and Barua, Rana. Provably secure constant round contributory group key agreement in dynamic setting. IEEE. p. 2007--2025 2008
 *   
 * 
 * @author Francesco Rossi
 * @version 0.1
 * 
 */

public class IB_BD_ZSS {
       boolean flag=false;
 boolean sign=true;
     System_Param parameter;
 User[] m;
 int n;

 Random rnd;
  
 IB_ZSS a;

 
 
 public IB_BD_ZSS(User[] m, int n, System_Param param) {
        this.m = m;
        this.n = n;
        parameter=param;
        a=new IB_ZSS(param);
    }
    
    
    
    
     public  void Round1()
        {  
            
          int i;
          Point Z;
          BigInt nn;
       
          
         for (i=0;i<n;i++)            
         {    rnd=new Random();
             
                 // choise ni
             m[i].getIbgka().setNi(new BigInt(parameter.getE().getGroupOrder().bitLength(),rnd));
                //  Zi = niP
             m[i].getIbgka().setZi(parameter.getE().getCurve().multiply(parameter.getP(), m[i].getIbgka().getNi()));
    
            
            // Point sigma=a.sign(m[i].getIbgka().getZi().toString(),m[i].getKzss());
              m[i].getIbs().setMsigma(a.sign(m[i].getIbgka().getZi().toString(),m[i].getKzss()));
        
         }
       
      
        }
      
      
     public void Round2()
        {  BigInt mi; 
          Hash ut=new Hash();
          int i,is,ip;
          Point X,Y,NZP;
      
          BigInt nn;
          try{
        
              
      
       for (i=0;i<n;i++)  
            {  
                ip = ((n+i-1) % n);
                is = (i+1) % n;
                
                if (n==2)
                { if (a.vrf(m[is].getIbgka().getZi().toString(), m[is].getID(), m[is].getIbs().getMsigma())) 
                    {flag=true;
                 //    System.out.println("Utente "+i+"Verifica firme"+is);  
                    }
                
                }
               else 
              if (n >2)   
              { if ((a.vrf(m[is].getIbgka().getZi().toString(), m[is].getID(), m[is].getIbs().getMsigma())) && (a.vrf(m[ip].getIbgka().getZi().toString(), m[ip].getID(), m[ip].getIbs().getMsigma()))) 
                   {flag=true;
                   
               //     System.out.println("Utente "+i+"Verificate firme "+ip+","+is);  
                   }
              }
              
            
            }
            
            
         // System.out.println("flag="+flag);  
        if (flag)
         for (i=0;i<n;i++)            
         {
            
             
             
              is = (i+1) % n;
              
              ip = ((n+i-1) % n);
        
              
              
       //   System.out.println("System out println ="+is+","+ip);
          
                             // Xi = niZi+i
               X = parameter.getE().getCurve().multiply(m[is].getIbgka().getZi(), m[i].getIbgka().getNi());
                  
                              //  niZi-1 
               NZP = parameter.getE().getCurve().multiply((m[ip].getIbgka().getZi()), m[i].getIbgka().getNi());
               //  X = m[i].getE().getCurve().multiply(m[is].getZi(), m[i].getNi());
               m[i].getIbgka().setXi(X);
               
                  // Yi = Xi - niZi-1
               m[i].getIbgka().setYi(parameter.getE().getCurve().subtract(X, NZP));
               
              //    if (sign)
             // signature of Yi
            m[i].getIbs().setMsigma(a.sign(m[i].getIbgka().getYi().toString(),m[i].getKzss()));
                  
                  
                  
        
         }
        }
   catch (Exception c)
   {   c.printStackTrace();
   }
        }
      
     
    public void KeyDerivation()
        {  
          int i,j,is,ip,ind,ind2;
          Point K,sum=null;
    
          Point kk=null;
          BigInt nn;
      
          
       
          
          
            if (flag)
        for (i=0;i<n;i++)  
            {  
               // Compute Xi
            for (j=0;j<n-1;j++)            
             { is = (i+j+1) % n;
               if (!a.vrf(m[is].getIbgka().getYi().toString(), m[is].getID(), m[is].getIbs().getMsigma())) 
                 flag=false;   
             }
            } 
       
          
           // For each mi 
      if (flag)
        for (i=0;i<n;i++)            
         {
       
          kk=m[i].getIbgka().getXi();
          sum =m[i].getIbgka().getXi();
          
          // Compute Xi
            for (j=0;j<n-1;j++)            
             { is = (i+j+1) % n;
                 
         
           
             // System.out.println("Calcolo  X["+is+"]=X["+((i+j)%n)+"]+Y["+is+"]");
              
              // Compute Xj with j != i    
           kk = parameter.getE().getCurve().add(kk,m[is].getIbgka().getYi());
              
           
     
              // K = Xi+ Xj
           sum = parameter.getE().getCurve().add(sum,kk);
           
           
            }
            
        //    System.out.println("**********************************************");
            
            
           m[i].getIbgka().setKi(sum);  
        //  System.out.println("User "+i+" Compute the key ");   
     //    System.out.println(m[i].getIbgka().getKi().toString());   
     
        }
         
    
         
        }
    
    
        public boolean getFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
 
    
    
    
    
}

 